#include "logging.h"
#ifdef WIN32
#include <Windows.h>
#endif

namespace kanon
{
    Logger::~Logger()
    {
        if (logFile_.is_open())
        {
            logFile_.close();
        }
    }

    void Logger::setLogFile(const std::string& filePath)
    {
        std::lock_guard<std::mutex> lock(mtx_);
        logFile_.open(filePath, std::ios::out | std::ios::app);
        if (!logFile_.is_open())
        {
            std::cerr << "Failed to open log file: " << filePath << std::endl;
        }
    }

    void Logger::setLogLevel(LogLevel level)
    {
        std::lock_guard<std::mutex> lock(mtx_);
        minLevel_ = level;
    }

    void Logger::log(LogLevel level, const char* format, ...)
    {
        if (level < minLevel_) return;

        std::lock_guard<std::mutex> lock(mtx_);
        std::string formattedLog = formatLogHead(level);

        va_list args;
        va_start(args, format);
        formattedLog += formatString(format, args);
        va_end(args);

        std::cout << formattedLog;
        if (logFile_.is_open())
        {
            logFile_ << formattedLog;
        }
#ifdef WIN32
        OutputDebugStringA(formattedLog.c_str());
#endif
    }

    void Logger::debug(const char* message, ...)
    {
        if (LogLevel::DEBUG >= minLevel_)
        {
            va_list args;
            va_start(args, message);
            log(LogLevel::DEBUG, message);
            va_end(args);
        }
    }

    void Logger::info(const char* message, ...)
    {
        if (LogLevel::INFO >= minLevel_)
        {
            va_list args;
            va_start(args, message);
            log(LogLevel::INFO, message);
            va_end(args);
        }
    }

    void Logger::warn(const char* message, ...)
    {
        if (LogLevel::WARN >= minLevel_)
        {
            va_list args;
            va_start(args, message);
            log(LogLevel::WARN, message);
            va_end(args);
        }
    }

    void Logger::error(const char* message, ...)
    {
        if (LogLevel::ERR >= minLevel_)
        {
            va_list args;
            va_start(args, message);
            log(LogLevel::ERR, message);
            va_end(args);
        }
    }

    void Logger::fatal(const char* message, ...)
    {
        if (LogLevel::FATAL >= minLevel_)
        {
            va_list args;
            va_start(args, message);
            log(LogLevel::FATAL, message);
            va_end(args);
        }
    }

    std::string Logger::formatLogHead(LogLevel level)
    {
        std::string levelStr;
        switch (level)
        {
        case LogLevel::DEBUG: levelStr = "[DEBUG]"; break;
        case LogLevel::INFO: levelStr = "[INFO]"; break;
        case LogLevel::WARN: levelStr = "[WARNING]"; break;
        case LogLevel::ERR: levelStr = "[ERROR]"; break;
        case LogLevel::FATAL: levelStr = "[FATAL]"; break;
        }

        std::time_t now = std::time(nullptr);
        char timeBuffer[80];
        std::strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
        return "[" + std::string(timeBuffer) + "] " + levelStr + " ";
    }

    std::string Logger::formatString(const char* format, va_list args)
    {
        char buffer[1024];
        vsnprintf(buffer, sizeof(buffer), format, args);
        return std::string(buffer);
    }
}